package sentinel

import (
	"config"
	"fmt"
	"github.com/garyburd/redigo/redis"
	"log"
	"time"
)

func parser(msg interface{}) interface{} {
	reply, err := redis.Values(msg, nil)
	if err != nil {
		return err
	}

	var kind string
	reply, err = redis.Scan(reply, &kind)
	if err != nil {
		return err
	}

	switch kind {
	case "message":
		var m redis.Message
		if _, err := redis.Scan(reply, &m.Channel, &m.Data); err != nil {
			return err
		}
		return m
	case "pmessage":
		var pm redis.PMessage
		if _, err := redis.Scan(reply, &pm.Pattern, &pm.Channel, &pm.Data); err != nil {
			return err
		}
		return pm
	case "subscribe", "psubscribe", "unsubscribe", "punsubscribe":
		s := redis.Subscription{Kind: kind}
		if _, err := redis.Scan(reply, &s.Channel, &s.Count); err != nil {
			return err
		}
		return s
	}
	return fmt.Errorf("redigo: unknown pubsub notification")
}

func subScribeSentinel() {
	if config.SentinelEnable != "yes" {
		return
	}

	sentinel, err := NewSentinelClient("tcp", config.SentinelAddrs, nil, 250*time.Millisecond, 0, 250*time.Millisecond)
	if err != nil {
		panic(err)
	}
	defer sentinel.Close()

	sentinel.Send("SUBSCRIBE", "+switch-master")
	sentinel.Flush()

	for {
		msg, err := sentinel.Receive()
		if err != nil {
			log.Println("sentinel subscribe err: ", err)
			StartSentinel()
			return
		}

		switch n := parser(msg).(type) {
		case redis.Message:
			log.Printf("Message: %s %s\n", n.Channel, n.Data)
			if n.Channel == "+switch-master" {
				doRecovery()
			}
		case redis.PMessage:
			log.Printf("PMessage: %s %s %s\n", n.Pattern, n.Channel, n.Data)
		case redis.Subscription:
			log.Printf("Subscription: %s %s %d\n", n.Kind, n.Channel, n.Count)
			if n.Count == 0 {
				return
			}
		case error:
			log.Printf("error: %v\n", n)
			StartSentinel()
			return
		default:
			log.Printf("unknow sentinel subscribe type message: %v\n", n)
		}
	}
}

func StartSentinel() {
	doRecovery()
	go subScribeSentinel()

}
